package com.recipedb.sprint.service.impl;

import com.recipedb.sprint.entity.Sessions;
import com.recipedb.sprint.entity.Users;
import com.recipedb.sprint.repository.SessionsRepository;
import com.recipedb.sprint.repository.UsersRepository;
import com.recipedb.sprint.service.LlmSessionService;
import com.recipedb.sprint.util.BashRunner;
import com.recipedb.sprint.util.LlmOutputConsumer;
import com.recipedb.sprint.util.PromptBuilder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class LlmSessionServiceImpl implements LlmSessionService {

    private final SessionsRepository sessionsRepository;
    private final UsersRepository usersRepository;
    private final BashRunner bashRunner;
    private final LlmOutputConsumer llmOutputConsumer;
    private final PromptBuilder promptBuilder;

    @Override
    @Transactional
    public Map<String, Object> createSessionAndRunLlm(Long userid, String userInput, String model, boolean useSystemPrompt, String preferences) {
        Users user = usersRepository.findById(userid)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在: " + userid));

        String finalPrompt = useSystemPrompt
                ? promptBuilder.buildPrompt(userInput, preferences)
                : userInput;

        String redisKey = "llm:session:" + UUID.randomUUID();

        bashRunner.runBashScriptAsync(redisKey, model, finalPrompt);

        Map<String, Object> result = new HashMap<>();
        result.put("redisKey", redisKey);

        if (useSystemPrompt) {
            Sessions session = Sessions.builder()
                    .userid(userid)
                    .prompt(finalPrompt)
                    .answer("")
                    .llmProvider(model)
                    .createdAt(LocalDateTime.now())
                    .updatedAt(LocalDateTime.now())
                    .build();
            Sessions savedSession = sessionsRepository.save(session);

            llmOutputConsumer.consumeStream(savedSession.getSessionid(), redisKey);

            log.info("✅ 会话创建并持久化 sessionid={}, redisKey={}", savedSession.getSessionid(), redisKey);

            result.put("sessionId", savedSession.getSessionid());
            result.put("success", true);
        } else {
            llmOutputConsumer.consumeStream(0L,redisKey);
            log.info("⚡ 非系统Prompt模式，仅推送到Redis，Key={}", redisKey);
            result.put("sessionId", null);
            result.put("success", true);
        }

        return result;
    }

    @Override
    public Sessions getSessionById(Long sessionId) {
        return sessionsRepository.findById(sessionId)
                .orElseThrow(() -> new IllegalArgumentException("会话不存在: " + sessionId));
    }

    @Override
    public void streamSession(Long sessionId, SseEmitter emitter) {
        // 原有的基于 sessionId 的流式传输
        String redisKey = "llm:session:" + sessionId;
        llmOutputConsumer.streamToEmitter(redisKey, emitter);
        log.info("📡 启动SSE流式传输 sessionId={}, redisKey={}", sessionId, redisKey);
    }

    @Override
    public void streamSessionByRedisKey(String redisKey, SseEmitter emitter) {
        // 新增：基于 Redis key 的直接流式传输
        llmOutputConsumer.streamToEmitter(redisKey, emitter);
        log.info("📡 启动SSE流式传输 redisKey={}", redisKey);
    }

    /**
     * 实现：查询用户自己的所有会话（按创建时间倒序）
     */
    @Override
    public List<Sessions> getUserOwnSessions(Long userId) {
        // 校验用户存在（避免查询无效用户）
        usersRepository.findById(userId)
                .orElseThrow(() -> new IllegalArgumentException("用户不存在: " + userId));

        // 调用Repository查询（需在SessionsRepository中定义该方法）
        return sessionsRepository.findByUseridOrderByCreatedAtDesc(userId);
    }


    /**
     * 实现：用户提交会话反馈（含权限校验）
     */
    @Override
    @Transactional
    public void submitFeedback(Long sessionId, Long userId, Integer rating, String feedback) {
        // 1. 校验会话存在
        Sessions session = sessionsRepository.findById(sessionId)
                .orElseThrow(() -> new IllegalArgumentException("会话不存在: " + sessionId));

        // 2. 权限校验：只能为自己的会话提交反馈
        if (!session.getUserid().equals(userId)) {
            throw new SecurityException("无权限操作该会话");
        }

        // 3. 校验评分有效性（1-5分）
        if (rating != null && (rating < 1 || rating > 5)) {
            throw new IllegalArgumentException("评分必须为1-5分");
        }

        // 4. 更新反馈字段和时间
        session.setRating(rating);
        session.setFeedback(feedback);
        session.setUpdatedAt(LocalDateTime.now()); // 更新时间戳
        sessionsRepository.save(session);

        log.info("📝 会话反馈提交成功，sessionId={}, userId={}", sessionId, userId);
    }

}